import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class myThread extends Thread {

	public int index;
	public String thrName;
	public int time;
	public List<myThread> nextThrs = new ArrayList<myThread>();
	public List<myThread> parallelThrs = new ArrayList<myThread>();
	public boolean sameNext = false;
	public boolean master = false;// main task in the parallel tasks, if
									// "master" is true

	public myThread(int index, String thrName, int time,
			ArrayList<myThread> nextThreads) {
		this.index = index;
		this.thrName = thrName;
		this.time = time;
		this.nextThrs.addAll(nextThreads);
	}

	public myThread(int index, String thrName, int time) {
		this.index = index;
		this.thrName = thrName;
		this.time = time;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(time * 1000);// time*1 second
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println(this.index + ", name: " + this.thrName + ", time: "
				+ this.time + ", tostring: " + this.toString());

		if (this.nextThrs.size() != 0) {
			// wait till all the parallel threads are over
			for (myThread thr : nextThrs) {
				if (this.sameNext) {
					if (this.master) {
						// wait till the end of this round
						waitForOtherThr(this.parallelThrs);
						thr.start();
					}
				} else {
					thr.start();
				}
			}
		}
	}

	/**
	 * wait till all the threads in the given parameter are finished
	 * @param myThreads
	 */
	public static void waitForOtherThr(List<myThread> myThreads){
		// wait till the end of this round
		boolean run = true;
		boolean temp;
		while (run) {
			temp = false;
			for (Thread mythr : myThreads) {
				temp |= mythr.isAlive();
			}
			run = temp;
		}
	}
	public static void main(String[] args) {
		// initial the tasks
		myThread thr1 = new myThread(1, "thr1", 1);
		myThread thr2 = new myThread(2, "thr2", 1);
		myThread thr3 = new myThread(3, "thr3", 1);
		myThread thr4 = new myThread(4, "thr4", 1);
		myThread thr5 = new myThread(5, "thr5", 1);
		myThread thr6 = new myThread(6, "thr6", 1);
		myThread thr7 = new myThread(7, "thr7", 3);
		myThread thr8 = new myThread(8, "thr8", 3);
		myThread thr9 = new myThread(9, "thr9", 1);
		myThread thr10 = new myThread(10, "thr10", 1);

		thr3.nextThrs.add(thr4);
		thr3.nextThrs.add(thr5);
		thr4.parallelThrs.add(thr5);
		thr5.parallelThrs.add(thr4);
		thr4.nextThrs.add(thr6);
		thr5.nextThrs.add(thr6);
		thr4.sameNext = true;
		thr5.sameNext = true;
		thr4.master = true;

		Map<Integer, myStructure> rounds = new TreeMap<Integer, myStructure>();

		rounds.put(1, new myStructure());
		rounds.put(2, new myStructure());
		rounds.put(3, new myStructure());
		rounds.put(4, new myStructure());

		rounds.get(1).getTasks().add(thr1);
		rounds.get(2).getTasks().add(thr2);
		rounds.get(3).getTasks().add(thr3);
		rounds.get(3).getTasks().add(thr4);
		rounds.get(3).getTasks().add(thr5);
		rounds.get(3).getTasks().add(thr6);
		rounds.get(3).getTasks().add(thr7);
		rounds.get(3).getTasks().add(thr8);
		rounds.get(4).getTasks().add(thr9);
		rounds.get(4).getTasks().add(thr10);

		rounds.get(1).getTopTasks().add(thr1);
		rounds.get(2).getTopTasks().add(thr2);
		rounds.get(3).getTopTasks().add(thr3);
		rounds.get(3).getTopTasks().add(thr7);
		rounds.get(3).getTopTasks().add(thr8);
		rounds.get(4).getTopTasks().add(thr9);
		rounds.get(4).getTopTasks().add(thr10);

		// run according to rounds
		for (Integer key : rounds.keySet()) {
			myStructure mystruc = rounds.get(key);
			for (Thread mythr : mystruc.getTopTasks()) {
				mythr.start();
			}
			// wait till the end of this round
			myThread.waitForOtherThr(mystruc.getTasks());
			System.out.println("============================");
		}
	}
}
